#!/bin/bash

set -e

base_directory="$(dirname "$0")"
export base_directory="$(readlink -f "$base_directory")"

export nrp_directory="$base_directory/.nrp"
export venv_directory="$base_directory/.venv"
export devtools_cli_directory="$nrp_directory/devtools"

echo "base_directory: $base_directory"

NRP_VERSION=1

# This script runs the NRP repository tools

# Environment variables
# PYTHON:
#              python executable to use for running the NRP tools
# LOCAL_NRP_DEVTOOLS_LOCATION:
#              location of the local NRP repository.
#              If set, do not clone the NRP repository but use the local one.


# If there is a local environment file, source it. This is necessary on Mac OS X
# to set the correct environment variables for the python executable.
# An example file on mac os x is:
#
# ❯ cat ~/.envrc.local
#
# # dynamic libraries (such as cairo)
# export DYLD_FALLBACK_LIBRARY_PATH=/opt/homebrew/lib
#
if [ -f ~/.envrc.local ] ; then
  source ~/.envrc.local
fi

PYTHON_VERSION="${PYTHON_VERSION:-3.12}"
SUPPORTED_PYTHON_PATHS=(
  "/usr/bin/python${PYTHON_VERSION}"
  "/opt/homebrew/bin/python${PYTHON_VERSION}"
  "/usr/local/bin/python${PYTHON_VERSION}"
)

if [ -z "$PYTHON" ] ; then

  # find a supported python
  for python_path in "${SUPPORTED_PYTHON_PATHS[@]}"; do
      if [ -x "$python_path" ] ; then
        # try to execute it
        if command -v $python_path >/dev/null 2>&1; then
            PYTHON=$python_path
            break
        fi
      fi
  done

  if [ -z "$PYTHON" ] ; then
    echo "No supported python found. Please install python 3.10
    or set the PYTHON environment variable to the python executable."
    exit 1
  fi
fi

echo "Will use python at path $PYTHON"
export PYTHON

check_create_nrp_venv() {

  if [ ! -d "$venv_directory" ] ; then
    mkdir "$venv_directory"
  fi

  # if there is a devtools directory and can not call nrp-devtools inside it,
  # remove the directory
  if [ -d "$devtools_cli_directory" ] ; then
    if ! "$devtools_cli_directory"/bin/nrp-devtools --help >/dev/null 2>&1 ; then
      rm -rf "$devtools_cli_directory"
    fi
  fi

  if [ ! -d "$devtools_cli_directory" ] ; then
    # make parent directory if it does not exist
    if [ ! -d "$(dirname "$devtools_cli_directory")" ] ; then
      mkdir -p "$(dirname "$devtools_cli_directory")"
    fi
    $PYTHON -m venv "${devtools_cli_directory}"
    "${devtools_cli_directory}"/bin/pip install -U setuptools pip wheel
    if [ -z "$LOCAL_NRP_DEVTOOLS_LOCATION" ] ; then
      "${devtools_cli_directory}"/bin/pip install "nrp-devtools==${NRP_VERSION}.*"
    else
      "${devtools_cli_directory}"/bin/pip install -e "$LOCAL_NRP_DEVTOOLS_LOCATION"
    fi
  fi
}

run_service() {
  service_name=$1
  shift

  cmd=$1
  shift

  echo "Checking if should run $service_name ..."

  while [ -f $nrp_directory/.run_${service_name} ] ; do
    echo "Trying to run $service_name ..."
    "$cmd" "$@" </dev/null &
    pid=$!
    echo "Running $service_name with pid $pid ..."
    echo "$pid" > $nrp_directory/.${service_name}_pid
    # wait up a bit if the process dies immediately
    sleep 10
    # wait for the process to finish
    while kill -0 "$pid" 2>/dev/null; do
      sleep 1
    done
  done
}


run_file_watcher() {
  touch "$nrp_directory/.run_watcher"
  run_service watcher \
    "$devtools_cli_directory"/bin/nrp-devtools watch
}

run_backend() {
  touch "$nrp_directory/.run_backend"
  run_service backend \
    "$venv_directory"/bin/invenio run \
    --cert $base_directory/docker/development.crt \
    --key $base_directory/docker/development.key </dev/null
}

run_frontend() {
  touch "$nrp_directory/.run_frontend"
  cd "$venv_directory"/var/instance/assets
  run_service frontend npm run start
}

stop_gracefully() {
  # check if process $1 exists and kill it
  if [ ! -f $1 ] ; then
    return
  fi
  pid=$(cat "$1")

  if kill -0 "$pid" 2>/dev/null; then
    kill $pid || true
  fi

  sleep 1

  if kill -0 "$pid" 2>/dev/null; then
    sleep 5
  fi

  if kill -0 "$pid" 2>/dev/null; then
    kill -9 $pid || true
  fi

  rm -f "$1" || true
}

stop_watcher() {
  stop_gracefully "$nrp_directory/.watcher_pid"
}

stop_backend() {
  stop_gracefully "$nrp_directory/.backend_pid"
}

stop_frontend() {
  stop_gracefully "$nrp_directory/.frontend_pid"
}

develop_cleanup() {
  rm -f "$nrp_directory/.run_watcher"
  rm -f "$nrp_directory/.run_backend"
  rm -f "$nrp_directory/.run_frontend"

  echo "Stopping watcher ..."
  stop_watcher
  echo "Stopping backend ..."
  stop_backend
  echo "Stopping frontend ..."
  stop_frontend

  exit 1
}


run_user_develop_input() {
  while true ; do
    echo
    echo "1 or server     - restart python server"
    echo "2 or ui         - restart webpack server"
    echo "0 or stop       - stop the server (Ctrl-C also works)"
    echo
    if read -t 30 -p "Enter command: " cmd ; then
      echo
      echo "Executing: $cmd"
      if [ "$cmd" == "stop" -o "$cmd" == "0" ] ; then
        break
      fi
      if [ "$cmd" == "server" -o "$cmd" == "1" ] ; then
        stop_backend
      elif [ "$cmd" == "frontend" -o "$cmd" == "2" ] ; then
        stop_frontend
      fi
    fi
  done
}

run_develop_with_shell() {
  # check if there is a develop --shell commands anywhere in arguments
  develop_called=0

  # Loop through all arguments
  for arg in "$@"; do
    if [[ "$arg" == "develop" ]]; then
      develop_called=1
    elif [[ "$arg" == "--shell" ]]; then
      return 0
    fi
  done
  return 1
}


# main entrypoint in here

check_create_nrp_venv
source "$devtools_cli_directory"/bin/activate
"$devtools_cli_directory"/bin/nrp-devtools "$@"

# if running nrp develop in shell,
# start the services and run the input cmd watcher
if run_develop_with_shell "$@" ; then
  # register cleanup at exit and sigint
  trap develop_cleanup EXIT
  trap develop_cleanup SIGINT

  run_file_watcher &
  sleep 2
  run_backend &
  sleep 2
  run_frontend &

  sleep 20
  run_user_develop_input
fi